<?php


namespace app\api\model;



use ApiOper;
use app\common\exception\BaseException;
use app\common\library\dingding\AliDingDing;
use app\common\library\IDMan;
use app\common\model\BaseModel;
use common;
use hiredis;
use think\db\Query;
use think\facade\Log;
use app\api\model\EventNoticeReceiverModel;

class BikeAlertModel extends BaseModel
{
    protected $name = 'bike_alert_order';
    protected $pk = 'id';

    var $_info = [];

    function ALERT_ID($city_id)
    {
        return $city_id . date('ymdHisu') . rand(1000, 9999);
    }

    function add($city_id, $bike_id, $type, $content)
    {
        $bike_info = BikeModel::instance()->get_info_by_id($bike_id);


        $bus_state = '空闲';
        if ($bike_info['bus_state'] == BIKE_BUS_STAT_RIDING) {
            $bus_state = '骑行';
        } else if ($bike_info['bus_state'] == BIKE_BUS_STAT_TEMP_PARK) {
            $bus_state = '骑行临时停车';
        } elseif ($bike_info['bus_state'] == BIKE_BUS_STAT_USER_REPARK) {
            $bus_state = '用户挪车';
        } elseif ($bike_info['bus_state'] == BIKE_BUS_STAT_OPER_REPARK) {
            $bus_state = '挪车';
        } elseif ($bike_info['bus_state'] == BIKE_BUS_STAT_BATTERY_CHANGE) {
            $bus_state = '换电池';
        }

        if ($type & BIKE_ALERT_STOLEN) {

            //确认消息
            $confirm_key = "CONFIRM_STOLEN_VMSG_" . $bike_info['sn'];
            if (hiredis::db()->exists($confirm_key)){
                //已经确认消息
            }
            else {
                //还未确认消息
                Log::debug("add_alert: {$type}, content={$content},bike_info:{$bike_info}");
                $key = "STOLEN_VMSG_" . $bike_info['sn'];
                if (hiredis::db()->incr($key) <= 1) {
                    hiredis::db()->expire($key, 300);
                    EventNoticeReceiverModel::instance()->send_vmsg_bike_stolen($city_id, $bike_info['sn'], $bus_state, $bike_info['speed'], $bike_info['address']);
                }
            }
        }

        if ($type & BIKE_ALERT_FAULT) {
            $key = "BIKE_REPORTED_BROKEN_COUNT|" . $bike_info['sn'] . "|" . date('Ymd');
            $c = hiredis::db()->incr($key);

            hiredis::db()->expire($key, 3600 * 24);
            if ($c < 3) {
                return;
            }
        }

        if ($bike_info['alert_state'] & $type){
            return;
        }

        Log::debug("add_alert: {$type}, content={$content},bike_info:{$bike_info}");
        if ($type & BIKE_ALERT_UNDER_VOLT) {
            EventNoticeReceiverModel::instance()->send_sms_bike_under_volt($city_id, $bike_info['sn']);
        } else if ($type & BIKE_ALERT_OFFLINE) {
            EventNoticeReceiverModel::instance()->send_sms_bike_offline($city_id, $bike_info['sn']);
        } else if ($type & BIKE_ALERT_EX_BATTERY_OFF) {
            EventNoticeReceiverModel::instance()->send_sms_bike_ex_off_battery($city_id, $bike_info['sn']);
            //EventNoticeReceiverModel::instance()->send_vmsg_bike_battery_off($city_id, $bike_info['sn'], $bus_state, $bike_info['address']);
        }

        $info = [
            'id' => IDMan::city_order_id($city_id),
            'city_id' => $city_id,
            'bike_id' => $bike_id,
            'bike_sn' => $bike_info['sn'],
            'type' => $type,
            'alert_content' => $content,
            'create_time' => date('Y-m-d H:i:s'),
            'order_state' => BIKE_ALERT_STATE_PENDING,
        ];

        if (!empty($bike_info)) {
            $info['health_state'] = $bike_info['health_state'];
            $info['is_wheel_locked'] = $bike_info['is_wheel_locked'];
            $info['battery_level'] = $bike_info['battery_level'];
            $info['is_acc_on'] = $bike_info['is_acc_on'];
            $info['is_battery_locked'] = $bike_info['is_battery_locked'];
            $info['is_under_volt'] = $bike_info['is_under_volt'];
            $info['coordinate'] = $bike_info['coordinate'];
            $info['address'] = $bike_info['address'];
        }

        ApiOper::instance()->append_creater_info($info);

        self::create($info,true);
        (new BikeMgr())->set_alert($city_id, $bike_id, $type, $content);


        $alert_desc = "";
        if ($bike_info['bus_state'] == BIKE_BUS_STAT_IDLE) {
            $alert_desc = $alert_desc . " [空闲]";
        } else if ($bike_info['bus_state'] == BIKE_BUS_STAT_RIDING) {
            $alert_desc = $alert_desc . " [骑行]";
        } else if ($bike_info['bus_state'] == BIKE_BUS_STAT_TEMP_PARK) {
            $alert_desc = $alert_desc . " [临停]";
        } else if ($bike_info['bus_state'] == BIKE_BUS_STAT_USER_REPARK) {
            $alert_desc = $alert_desc . "[用户挪车]";
        } else if ($bike_info['bus_state'] == BIKE_BUS_STAT_OPER_REPARK) {
            $alert_desc = $alert_desc . "[挪车]";
        } else if ($bike_info['bus_state'] == BIKE_BUS_STAT_BATTERY_CHANGE) {
            $alert_desc = $alert_desc . " [换电]";
        }

        if ($bike_info['is_defend_on']) {
            $alert_desc = $alert_desc . " [设防]";
        } else {
            $alert_desc = $alert_desc . " [撤防]";
        }
        if ($bike_info['is_acc_on']) {
            $alert_desc = $alert_desc . " [电门开]，";
        } else {
            $alert_desc = $alert_desc . " [电门关]";
        }
        if ($bike_info['is_online']) {
            $alert_desc = $alert_desc . "[在线]";
        } else {
            $alert_desc = $alert_desc . "[离线更新时间{$bike_info['online_update_time']}]";
        }

        $citys = (new CityModel())->query_all(0, 100);
        $city_name = $city_id;
        foreach ($citys as $city) {
            if ($city['id'] == $city_id) {
                $city_name = $city['name'];
                break;
            }
        }
        $alert_desc = $alert_desc . ' [电压:' . $bike_info['battery_volt'] . " {$bike_info['battery_level']}%]";
        $alert_desc = $alert_desc . " [定位类型: {$bike_info['locate_type']} {$bike_info['gps_update_time']} ] [ 异常时间" . date('Y-m-d H:i:s') . "]";
        $d = new AliDingDing(config('app.bike_alert_ding_ding_token')); //'7d9d1cccf177547d6a96ce3ba6da55497308394df3490d83dee8c0ffcb60bc30'
        $d->assign('text', "{$city_name} {$bike_info['sn']} [{$content}]! " . $alert_desc)
            ->at(true)
            ->send();

        return $info;
    }

    function confirm($city_id, $id,$bike_sn,$type)
    {
        $data = [
            'order_state' => BIKE_ALERT_STATE_CONFIRMED,
            'confirm_time' => date('Y-m-d H:i:s'),
            'confirmer_id' => ApiOper::instance()->userinfo()['id'],
            'confirmer_name' =>ApiOper::instance()->userinfo()['name'],
        ];
        $where = [
            'city_id' => $city_id,
            'id' => $id,
        ];
        self::update($data, $where);

        if ($type & BIKE_ALERT_STOLEN) {
            //设置flag标志
            $confirm_key = "CONFIRM_STOLEN_VMSG_" . $bike_sn;
            hiredis::db()->set($confirm_key,"1");
            hiredis::db()->expire($confirm_key,3600*12);
        }
    }

    function handle($city_id, $id, $result, $remark)
    {
        $alert_info = $this->info($city_id, $id);
        if (empty($alert_info)) {
           $this->throw_myexception(ERROR_QUERY_INFO, "获取订单失败!");
        }

        if ($alert_info['order_state'] >= BIKE_ALERT_STATE_SOLVED) {
            $this->throw_myexception(ERROR_STATE_DISMATCH, "获取订单失败!");
        }
        $data = [
            'order_state' => BIKE_ALERT_STATE_SOLVED,
            'handle_result' => $result,
            'handle_note' => $remark,
            'handle_time' => date('Y-m-d H:i:s'),
            'duration' => time() - strtotime($alert_info['create_time']),
        ];

        $where = " city_id = '{$city_id }' and id = '{$id}'";
        self::update($data,$where);
        $where = [
            'city_id' => $city_id,
            'id' => $id,
        ];
        self::update($data, $where);

        if ($result == BIKE_ALERT_RESULT_SOLVED) {
            BikeModel::instance()->unset_alert($city_id, $alert_info['bike_id'], $alert_info['type']);

            if ($alert_info['type'] & BIKE_ALERT_STOLEN) {
                //设置flag标志
                $confirm_key = "CONFIRM_STOLEN_VMSG_" . $alert_info['bike_sn'];
                hiredis::db()->del($confirm_key);
            }
        }
    }

    function get_list($city_id, $condition, $pos, $limit)
    {
        $selectlist = [
            'id' => 'string',
            'city_id' => 'string',
            'bike_id' => 'string',
            'bike_sn' => 'string',
            'type' => 'int',
            'alert_content' => 'string',
            'order_state' => 'int',
            'duration' => 'int',
            'handle_result' => 'int',
            'handle_note' => 'string',
            'is_under_volt' => 'int',
            'battery_level' => 'int',
            'health_state' => 'int',
            'coordinate' => 'array',
            'address' => 'string',
            'handler_id' => 'string',
            'handler_name' => 'string',
            'handle_time' => 'string ',
            'confirmer_id' => 'string',
            'confirmer_name' => 'string',
            'confirm_time' => 'string ',
            'creator_id' => 'string',
            'creator_name' => 'string',
            'create_time' => 'string ',
            'baseon' => 'string',
        ];

        $beans = [
            'city_id' =>$city_id,
        ];

        $query = new Query();
        $query2 = new Query();
        if (isset($condition['type'])) {
            $query->whereRaw("(type & :type) > 0",$condition['type']);
        }
        if (isset($condition['order_state'])) {
            $beans['order_state'] = $condition['order_state'];
        }
        if (isset($condition['is_solved'])) {
            if ($condition['is_solved']) {
                $beans['order_state'] = BIKE_ALERT_STATE_SOLVED;
            } else {
                $beans['order_state'] = ['<',BIKE_ALERT_STATE_SOLVED];
            }
        }
        if (isset($condition['is_under_volt'])) {
            $beans['is_under_volt'] = $condition['is_under_volt'];
        }
        if (isset($condition['bike_id'])) {
            $beans['bike_id'] = $condition['bike_id'];
        }
        if (isset($condition['health_state'])) {
            $beans['health_state'] = $condition['health_state'];
        }
        if (isset($condition['start_time'])) {
            $beans['create_time'] = ['>=',$condition['start_time']];
        }
        if (isset($condition['end_time'])) {
            $beans['create_time'] = ['<=',$condition['end_time']];
        }

        if (isset($condition['types'])) {
            $beans['type'] = ['in',$condition['types']];
        }

        if (isset($condition['duration_interval'])) {
            $intv = $condition['duration_interval'];
            if ($intv && count($intv) == 2) {
                $ds = intval($intv[0]);
                $de = intval($intv[1]);
                $start_time_low = date('Y-m-d H:i:s', time() - $de);
                $start_time_up = date('Y-m-d H:i:s', time() - $ds);

                $map1 = [
                    ['duration', '<>', 'null'],
                    ['duration', '>=', intval($ds)],
                    ['duration', '<=', intval($de)]
                ];

                $map2 = [
                    ['duration', '=', 'null'],
                    ['create_time', '>=', $start_time_low],
                    ['create_time', '<=', $start_time_up]
                ];

                $query2->whereOr([$map1,$map2 ]);
            }
        }
        if (isset($condition['sk']) && !empty($condition['sk'])) {
            if (IDMan::is_bike_sn($condition['sk'])) {
                $beans['bike_sn'] = $condition['sk'];
            }
        }
        $rows = $this->where($beans)->where($query)->where($query2)->field(common::array_keys($selectlist))->order('create_time','desc')->limit($pos,$limit)->select();
        if ($rows->isEmpty()) {
            return [];
        }
        return $rows->toArray();
    }

    function info($city_id, $id)
    {
        $selectlist = [
            'id' => 'string',
            'city_id' => 'string',
            'bike_id' => 'string',
            'bike_sn' => 'string',
            'type' => 'int',
            'alert_content' => 'string',
            'order_state' => 'int',
            'handle_result' => 'int',
            'duration' => 'int',
            'handle_note' => 'string',
            'is_under_volt' => 'int',
            'battery_level' => 'int',
            'health_state' => 'int',
            'coordinate' => 'array',
            'address' => 'string',
            'handler_id' => 'string',
            'baseon' => 'string',
            'handler_name' => 'string',
            'handle_time' => 'string ',
            'confirmer_id' => 'string',
            'confirmer_name' => 'string',
            'confirm_time' => 'string ',
            'creator_id' => 'string',
            'creator_name' => 'string',
            'create_time' => 'string ',
        ];

        $beans = [
            'city_id' => $city_id,
            'id' => $id
        ];

        $row = $this->where($beans)->field(common::array_keys($selectlist))->find();
        if ($row->isEmpty()) {
            return null;
        }

        return $row;
    }
}